// import { cloneDeep } from 'lodash-es'
import { ref, unref, computed, watch } from 'vue'
import { useComDesignStoreWithOut, getCustomComDesignInfo } from '@/store'

import {
  getNodeComAttrs,
  BwComTypeEnum,
  BwCustomComPropDataTypeEnum as BwPropDataTypeEnum,
  BwCustomComNodeAttrFromTypeEnum as BwAttrFromTypeEnum,
  BwCustomComNodeAttrDataTypeEnum as BwAttrDataTypeEnum,
  type BwCustomComNodeAttrModel,
} from '@bitwit/base-com-render'
import type { BwCurNodeAttrInfoModel } from './model'

/** 节点属性配配置 */
export function useNodeAttrs() {
  const designStore = useComDesignStoreWithOut()

  const curNodeId = ref<string>('')
  const curNodeAttrList = ref<Array<BwCurNodeAttrInfoModel>>([])
  const curNodeAttrData = ref<Record<string, BwCustomComNodeAttrModel>>({})
  const curNodeAttrDataTypes = ref<Record<string, BwAttrDataTypeEnum | null>>(
    {}
  )
  const curNodeAttrValueFroms = ref<Record<string, BwAttrFromTypeEnum>>({})
  const bwNodeAttrFromTypeList = computed(() => {
    const list = [
      { value: BwAttrFromTypeEnum.constValue, label: '常量' },
      { value: BwAttrFromTypeEnum.comProps, label: '外放属性' },
      { value: BwAttrFromTypeEnum.comVar, label: '组件变量' },
      { value: BwAttrFromTypeEnum.JSExpression, label: 'js表达式' },
    ]
    return list
  })

  /** 修改属性值 */
  const onChangeAttrValue = (name: string, value: any) => {
    const valueFrom = unref(curNodeAttrValueFroms)[name]
    const valueDataType = unref(curNodeAttrDataTypes)[name]

    const cusComAttrs = unref(curNodeAttrData)

    cusComAttrs[name] = cusComAttrs[name] ?? {}
    cusComAttrs[name].valueFromType = valueFrom
    cusComAttrs[name].valueDataType = valueDataType
    switch (valueFrom) {
      case BwAttrFromTypeEnum.JSExpression: {
        cusComAttrs[name].jsExpParams = value.jsExpParams
        cusComAttrs[name].jsExpBodyLogic = value.jsExpBodyLogic
        break
      }
      case BwAttrFromTypeEnum.comProps: {
        cusComAttrs[name].comPropsName = value
        break
      }
      case BwAttrFromTypeEnum.comVar: {
        cusComAttrs[name].comVarName = value
        break
      }
      case BwAttrFromTypeEnum.constValue: {
        cusComAttrs[name].constValue = value
        break
      }
    }

    designStore.onChangeNodeEleAttrs(unref(curNodeId), cusComAttrs)
  }

  /** 修改属性值来源 */
  const onChangeAttrValueFrom = (name: string, value: BwAttrFromTypeEnum) => {
    const cusComAttrs = unref(curNodeAttrData)

    cusComAttrs[name] = cusComAttrs[name] ?? {}
    cusComAttrs[name].valueFromType = value
    designStore.onChangeNodeEleAttrs(unref(curNodeId), cusComAttrs)
  }

  /** 修改属性值数据类型 */
  const onChangeAttrValueDataType = (
    name: string,
    value: BwAttrDataTypeEnum
  ) => {
    const cusComAttrs = unref(curNodeAttrData)

    cusComAttrs[name] = cusComAttrs[name] ?? {}
    cusComAttrs[name].valueDataType = value
    designStore.onChangeNodeEleAttrs(unref(curNodeId), cusComAttrs)
  }

  /** 获取属性值类型选择组件配置 */
  const getAttrDataTypeOptions = (data: BwCurNodeAttrInfoModel) => {
    const curProps: Record<string, any> = {}
    const dataType = data.dataType
    if (Array.isArray(dataType) && dataType.length) {
      curProps.options = []
      dataType.forEach((item) => {
        switch (item) {
          case BwPropDataTypeEnum.array: {
            curProps.options.push({
              label: '数组',
              value: item,
            })
            break
          }
          case BwPropDataTypeEnum.boolean: {
            curProps.options.push({
              label: '布尔值',
              value: item,
            })
            break
          }
          case BwPropDataTypeEnum.number: {
            curProps.options.push({
              label: '数字',
              value: item,
            })
            break
          }
          case BwPropDataTypeEnum.object: {
            curProps.options.push({
              label: '对象',
              value: item,
            })
            break
          }
          case BwPropDataTypeEnum.string: {
            curProps.options.push({
              label: '字符串',
              value: item,
            })
            break
          }
        }
      })
    }

    return curProps
  }

  const toAttrDataType = (type?: BwPropDataTypeEnum) => {
    switch (type) {
      case BwPropDataTypeEnum.array: {
        return BwAttrDataTypeEnum.array
      }
      case BwPropDataTypeEnum.boolean: {
        return BwAttrDataTypeEnum.boolean
      }
      case BwPropDataTypeEnum.number: {
        return BwAttrDataTypeEnum.number
      }
      case BwPropDataTypeEnum.object: {
        return BwAttrDataTypeEnum.object
      }
      case BwPropDataTypeEnum.string: {
        return BwAttrDataTypeEnum.string
      }
      default: {
        return null
      }
    }
  }

  /** 初始化节点属性偏配置 */
  const initNodeAttrsConfig = (
    comName: string,
    curAttrs: Record<string, BwCustomComNodeAttrModel>
  ) => {
    const list = getNodeComAttrs(comName)

    curNodeAttrList.value = []
    curNodeAttrDataTypes.value = {}
    curNodeAttrValueFroms.value = {}
    if (Array.isArray(list) && list.length) {
      list.forEach((item) => {
        const curAttrItem = curAttrs[item.key]

        curNodeAttrDataTypes.value[item.key] =
          curAttrItem?.valueDataType ??
          toAttrDataType(item.defaultValueDataType ?? undefined)
        curNodeAttrValueFroms.value[item.key] =
          curAttrItem?.valueFromType ?? BwAttrFromTypeEnum.constValue
        curNodeAttrList.value.push({
          isExpand: true,

          key: item.key,
          name: item.name,
          isModel: !!item.isModel,
          isRequire: !!item.isRequire,
          dataType: item.dataType,
          defaultValue: item.defaultValue,
          defaultValueDataType: item.defaultValueDataType,
          constValueSetCom: item.constValueSetCom,
          constValueSetComProps: item.constValueSetComProps,
          remark: item.remark,
        })
      })
    }
  }

  /** 初始化节点属性偏配置 - 自定义组件 */
  const initCustomComAttrsConfig = (
    comName: string,
    appCode: Nullable<string>,
    curAttrs: Record<string, BwCustomComNodeAttrModel>
  ) => {
    if (appCode) {
      getCustomComDesignInfo(appCode, comName).then((comInfo) => {
        if (comInfo) {
          curNodeAttrList.value = []
          curNodeAttrDataTypes.value = {}
          curNodeAttrValueFroms.value = {}

          const curProps = comInfo.comProps
          if (Array.isArray(curProps) && curProps.length) {
            curProps.forEach((item) => {
              const curAttrItem = curAttrs[item.key]

              curNodeAttrDataTypes.value[item.key] =
                curAttrItem?.valueDataType ??
                toAttrDataType(item.defaultValueDataType ?? undefined)
              curNodeAttrValueFroms.value[item.key] =
                curAttrItem?.valueFromType ?? BwAttrFromTypeEnum.constValue
              curNodeAttrList.value.push({
                ...item,
                isExpand: true,
              })
            })
          }
        }
      })
    }
  }

  watch(
    () => designStore.selectNodeEle,
    (newVal) => {
      curNodeId.value = ''
      if (newVal) {
        const comName = newVal.comName
        const comType = newVal.comType
        const comAppCode = newVal.comAppCode
        const curAttrs = newVal.attrs ?? {}

        curNodeId.value = newVal.nodeId
        curNodeAttrData.value = curAttrs
        switch (comType) {
          case BwComTypeEnum.custom: {
            initCustomComAttrsConfig(comName, comAppCode, curAttrs)
            break
          }
          default: {
            initNodeAttrsConfig(comName, curAttrs)
          }
        }
      }
    },
    { deep: true, immediate: true }
  )

  return {
    curNodeAttrList,
    curNodeAttrData,
    curNodeAttrDataTypes,
    curNodeAttrValueFroms,
    bwNodeAttrFromTypeList,

    onChangeAttrValue,
    onChangeAttrValueFrom,
    getAttrDataTypeOptions,
    onChangeAttrValueDataType,
  }
}
